package com.sign.utils.sm2;

import org.bouncycastle.asn1.ASN1Integer;
import org.bouncycastle.asn1.ASN1OctetString;
import org.bouncycastle.asn1.cms.ecc.ECCCMSSharedInfo;
import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
import org.bouncycastle.jcajce.provider.asymmetric.ec.GMCipherSpi;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.jce.spec.ECNamedCurveGenParameterSpec;
import org.bouncycastle.openssl.PEMKeyPair;
import org.bouncycastle.openssl.PEMParser;
import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter;
import org.bouncycastle.operator.InputDecryptorProvider;
import org.bouncycastle.pkcs.PKCS10CertificationRequest;
import org.bouncycastle.pkcs.PKCS8EncryptedPrivateKeyInfo;
import org.bouncycastle.pkcs.jcajce.JcePKCSPBEInputDecryptorProviderBuilder;
import org.bouncycastle.util.encoders.Hex;
import org.springframework.util.ResourceUtils;

import java.io.*;
import java.nio.charset.StandardCharsets;
import java.security.PublicKey;
import java.security.Security;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.Base64;

public class CertManagerBC {

    public static void showCertInfo() {
        try {
            // 读取证书文件
            String filePath = "D:\\dev\\test\\test.crt";
            File file = new File(filePath);
            InputStream inStream = new FileInputStream(file);
            // 引入BC库  证书类型是SM2证书时使用
            Security.addProvider(new BouncyCastleProvider());
            // 创建X509工厂类
            CertificateFactory cf = CertificateFactory.getInstance("X.509", "BC");
            // 创建证书对象
            X509Certificate cert = (X509Certificate) cf.generateCertificate(inStream);
            PublicKey pk = cert.getPublicKey();
            System.out.println(pk);
            System.out.println("Base64公钥信息:\n" + Base64.getMimeEncoder().encodeToString(pk.getEncoded()));
            System.out.println("16进制公钥信息：\n" + Hex.toHexString(pk.getEncoded()));
            System.out.println("----------------------------");
            System.out.println("证书版本:" + cert.getVersion());
            System.out.println("证书序列号:" + cert.getSerialNumber().toString(16));
            System.out.println("证书生效日期:" + cert.getNotBefore());
            System.out.println("证书失效日期:" + cert.getNotAfter());
            System.out.println("证书拥有者:" + cert.getSubjectDN().getName());
            System.out.println("证书颁发者:" + cert.getIssuerDN().getName());
            System.out.println("证书签名算法:" + cert.getSigAlgName());
            inStream.close();
        } catch (Exception e) {
            System.out.println("解析证书出错！");
            e.printStackTrace();
        }
    }

    // CSR 文件解析
    public static PKCS10CertificationRequest parseCsr(String csrFilePath) throws Exception {
        // 创建PEM解析器
        PEMParser pemParser = new PEMParser(new FileReader(csrFilePath));
        // 解析Csr文件为PKCS10CertificationRequest对象
        PKCS10CertificationRequest csr = (PKCS10CertificationRequest) pemParser.readObject();
        pemParser.close();
        return csr;
    }
    // 从CSR文件中获取公钥
    public static SubjectPublicKeyInfo extractPublicKey(PKCS10CertificationRequest csr) {
        // 提取公钥信息
        SubjectPublicKeyInfo publicKeyInfo = csr.getSubjectPublicKeyInfo();

        return publicKeyInfo;
    }
    // 从CSR文件中 将公钥信息转换为字符串形式
    public static String processPublicKey(SubjectPublicKeyInfo publicKeyInfo) {
        // 将公钥信息转换为字符串形式
        String publicKeyString = publicKeyInfo.toString();

        return publicKeyString;
    }





    private static final String PRIVATE_KEY_FILE = "prikey.pem";

    /**
     * 读取带密码保护的私钥文件
     * @param passwd 保护密码
     * @return 私钥的byte数组，可以通过Base64编码转为字符串
     */
    public static byte[] readPrivateKeyFromPem(String passwd,String path) throws Exception {
        //File file = ResourceUtils.getFile("classpath:".concat(PRIVATE_KEY_FILE));
        //String encrypted = FileUtil.readString(file, StandardCharsets.UTF_8);
        // 读取带密码保护的私钥：https://cloud.tencent.com/developer/article/2186682?from=15425
        PrivateKeyInfo pki;
        try (PEMParser pemParser = new PEMParser(new FileReader(path))) {
            Object o = pemParser.readObject();

            ECCCMSSharedInfo sharedInfo = (ECCCMSSharedInfo)o;
            PrivateKeyInfo privateKeyInfo = ((PEMKeyPair) o).getPrivateKeyInfo();

            /*PKCS8EncryptedPrivateKeyInfo epki = (PKCS8EncryptedPrivateKeyInfo) o;
            // 手动添加BC的安全模式：https://blog.csdn.net/Roy_70/article/details/70842322
            Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
            JcePKCSPBEInputDecryptorProviderBuilder builder =
                    new JcePKCSPBEInputDecryptorProviderBuilder().setProvider("BC");
            InputDecryptorProvider idp = builder.build(passwd.toCharArray());
            pki = epki.decryptPrivateKeyInfo(idp);*/
            ASN1OctetString privateKey = privateKeyInfo.getPrivateKey();
            byte[] encoded = privateKey.getEncoded();
            /*JcaPEMKeyConverter converter = new JcaPEMKeyConverter().setProvider("BC");
            return converter.getPrivateKey(privateKeyInfo).getEncoded();
*/
            return encoded;
        }
    }










    public static void main(String[] args) throws Exception {
        CertManagerBC certManager = new CertManagerBC();
        //certManager.showCertInfo();


       String privateStr = Base64.getEncoder().encodeToString( readPrivateKeyFromPem("12345678","D:\\dev\\test\\test.crt"));
        System.out.println(privateStr);
    }
}
